#!/usr/bin/env node

/**
 * Example HTTP client for Java Decompiler HTTP Server
 * Demonstrates how to use the REST API endpoints
 */

import axios from 'axios';

class JavaDecompilerClient {
  constructor(baseUrl = 'http://localhost:3000') {
    this.baseUrl = baseUrl;
    this.client = axios.create({
      baseURL: baseUrl,
      timeout: 60000,
      headers: {
        'Content-Type': 'application/json'
      }
    });
  }

  async healthCheck() {
    try {
      const response = await this.client.get('/health');
      return response.data;
    } catch (error) {
      throw new Error(`Health check failed: ${error.message}`);
    }
  }

  async getApiInfo() {
    try {
      const response = await this.client.get('/api/info');
      return response.data;
    } catch (error) {
      throw new Error(`API info failed: ${error.message}`);
    }
  }

  async searchArtifacts(query) {
    try {
      const response = await this.client.post('/api/search-artifacts', { query });
      return response.data;
    } catch (error) {
      throw new Error(`Search artifacts failed: ${error.message}`);
    }
  }

  async downloadArtifact(groupId, artifactId, version, packaging = 'jar') {
    try {
      const response = await this.client.post('/api/download-artifact', {
        groupId,
        artifactId,
        version,
        packaging
      });
      return response.data;
    } catch (error) {
      throw new Error(`Download artifact failed: ${error.message}`);
    }
  }

  async searchClasses(query, artifactId = null) {
    try {
      const body = { query };
      if (artifactId) body.artifactId = artifactId;
      
      const response = await this.client.post('/api/search-classes', body);
      return response.data;
    } catch (error) {
      throw new Error(`Search classes failed: ${error.message}`);
    }
  }

  async decompileClass(groupId, artifactId, version, className) {
    try {
      const response = await this.client.post('/api/decompile-class', {
        groupId,
        artifactId,
        version,
        className
      });
      return response.data;
    } catch (error) {
      throw new Error(`Decompile class failed: ${error.message}`);
    }
  }

  async getVersions(groupId, artifactId) {
    try {
      const response = await this.client.post('/api/get-versions', {
        groupId,
        artifactId
      });
      return response.data;
    } catch (error) {
      throw new Error(`Get versions failed: ${error.message}`);
    }
  }

  async scanProject(projectPath) {
    try {
      const response = await this.client.post('/api/scan-project', {
        projectPath
      });
      return response.data;
    } catch (error) {
      throw new Error(`Scan project failed: ${error.message}`);
    }
  }

  async searchLocalRepository(query) {
    try {
      const response = await this.client.post('/api/search-local-repository', {
        query
      });
      return response.data;
    } catch (error) {
      throw new Error(`Search local repository failed: ${error.message}`);
    }
  }

  async findClassInLocalRepository(className, repositoryPath = null) {
    try {
      const body = { className };
      if (repositoryPath) body.repositoryPath = repositoryPath;
      
      const response = await this.client.post('/api/find-class-local', body);
      return response.data;
    } catch (error) {
      throw new Error(`Find class in local repository failed: ${error.message}`);
    }
  }
}

// Example usage
async function runExamples() {
  const client = new JavaDecompilerClient();

  try {
    console.log('🔍 Testing Java Decompiler HTTP API...\n');

    // Health check
    console.log('1. Health Check:');
    const health = await client.healthCheck();
    console.log('   Status:', health.status);
    console.log('   Timestamp:', health.timestamp);
    console.log();

    // API info
    console.log('2. API Info:');
    const info = await client.getApiInfo();
    console.log('   Name:', info.name);
    console.log('   Version:', info.version);
    console.log('   Available endpoints:', info.endpoints.length);
    console.log();

    // Search artifacts
    console.log('3. Search Artifacts (spring-boot-starter):');
    const artifacts = await client.searchArtifacts('spring-boot-starter');
    console.log(`   Found ${artifacts.found} artifacts`);
    if (artifacts.artifacts.length > 0) {
      console.log('   First artifact:', artifacts.artifacts[0]);
    }
    console.log();

    // Download specific artifact
    console.log('4. Download Artifact (commons-lang3):');
    const download = await client.downloadArtifact(
      'org.apache.commons',
      'commons-lang3',
      '3.12.0'
    );
    if (download.success) {
      console.log(`   Downloaded successfully! Found ${download.classCount} classes`);
      console.log('   First few classes:', download.classes.slice(0, 3).map(c => c.fullName));
    }
    console.log();

    // Search classes in downloaded artifact
    console.log('5. Search Classes (StringUtils):');
    const classes = await client.searchClasses('StringUtils');
    if (classes.totalMatches > 0) {
      console.log(`   Found ${classes.totalMatches} matching classes`);
      console.log('   First match:', classes.matches[0]);
      
      // Decompile the first match
      const firstMatch = classes.matches[0];
      console.log('\n6. Decompile Class:');
      const decompiled = await client.decompileClass(
        firstMatch.artifact.groupId,
        firstMatch.artifact.artifactId,
        firstMatch.artifact.version,
        firstMatch.fullName
      );
      
      if (decompiled.success) {
        console.log(`   Decompiled ${decompiled.className} successfully!`);
        console.log('   Source length:', decompiled.source.length, 'characters');
        console.log('   First 200 characters:');
        console.log('  ', decompiled.source.substring(0, 200) + '...');
      }
    }
    console.log();

    // Get versions
    console.log('7. Get Versions (commons-lang3):');
    const versions = await client.getVersions('org.apache.commons', 'commons-lang3');
    console.log(`   Found ${versions.versions.length} versions`);
    console.log('   Latest versions:', versions.versions.slice(0, 5));
    console.log();

    // Search local repository
    console.log('8. Search Local Repository (commons):');
    const localSearch = await client.searchLocalRepository('commons');
    console.log(`   Found ${localSearch.found} local artifacts`);
    if (localSearch.artifacts.length > 0) {
      console.log('   First local artifact:', localSearch.artifacts[0]);
    }
    console.log();

    console.log('✅ All examples completed successfully!');

  } catch (error) {
    console.error('❌ Error running examples:', error.message);
    
    // Check if server is running
    try {
      await client.healthCheck();
    } catch (healthError) {
      console.error('\n💡 Make sure the HTTP server is running:');
      console.error('   npm run dev:http');
      console.error('   # or');
      console.error('   npm run build && npm run start:http');
    }
  }
}

// Python client example (as string for reference)
const pythonClientExample = `
import requests
import json

class JavaDecompilerClient:
    def __init__(self, base_url="http://localhost:3000"):
        self.base_url = base_url
        self.session = requests.Session()
        self.session.headers.update({'Content-Type': 'application/json'})
    
    def health_check(self):
        response = self.session.get(f"{self.base_url}/health")
        response.raise_for_status()
        return response.json()
    
    def search_artifacts(self, query):
        response = self.session.post(f"{self.base_url}/api/search-artifacts", 
                                   json={"query": query})
        response.raise_for_status()
        return response.json()
    
    def download_artifact(self, group_id, artifact_id, version, packaging="jar"):
        response = self.session.post(f"{self.base_url}/api/download-artifact", 
                                   json={
                                       "groupId": group_id,
                                       "artifactId": artifact_id,
                                       "version": version,
                                       "packaging": packaging
                                   })
        response.raise_for_status()
        return response.json()
    
    def decompile_class(self, group_id, artifact_id, version, class_name):
        response = self.session.post(f"{self.base_url}/api/decompile-class", 
                                   json={
                                       "groupId": group_id,
                                       "artifactId": artifact_id,
                                       "version": version,
                                       "className": class_name
                                   })
        response.raise_for_status()  
        return response.json()

# Usage example:
# client = JavaDecompilerClient()
# print(client.health_check())
# artifacts = client.search_artifacts("spring-boot")
# print(f"Found {artifacts['found']} artifacts")
`;

// Run examples if this file is executed directly
if (import.meta.url === `file://${process.argv[1]}`) {
  runExamples();
}

export { JavaDecompilerClient };

// Log Python example for reference
console.log('\n📝 Python client example saved in pythonClientExample variable');
console.log('   You can also create a similar client in Python using the requests library');